/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package botsim;

import com.ardor3d.framework.DisplaySettings;
import com.ardor3d.framework.NativeCanvas;
import com.ardor3d.framework.jogl.JoglCanvas;
import com.ardor3d.framework.jogl.JoglCanvasRenderer;
import com.ardor3d.framework.lwjgl.LwjglCanvas;
import com.ardor3d.framework.lwjgl.LwjglCanvasRenderer;
import com.ardor3d.input.PhysicalLayer;
import com.ardor3d.input.control.FirstPersonControl;
import com.ardor3d.input.logical.LogicalLayer;
import com.ardor3d.input.lwjgl.LwjglKeyboardWrapper;
import com.ardor3d.input.lwjgl.LwjglMouseWrapper;
import com.ardor3d.math.Vector3;
import com.ardor3d.util.Timer;

/**
 *
 * @author Prasanna Velagapudi <pkv@cs.cmu.edu>
 */
public class ArdorWindow implements Runnable {
    /**
     * Define some static data so that we can chose what rendering do user LWJGL of JOGL
     * default is LWJGL
     */
    public final static int LWJGL_RENDERER = 0;
    public final static int JOGL_RENDERER = 1;

    /**
     * This is our window where in our BulletScene is displayed
     */
    private final NativeCanvas _canvas;

    /**
     * This is the BulletScene we are displaying
     */
    private final BulletScene _scene;

    /**
     * Timer to keep track how much time has passed between frames
     */
    private final Timer _timer;

    /**
     * Logical layer that is used to trigger events on input
     */
    private LogicalLayer _logicalLayer;

    /**
     * boolean that says when to exit
     */
    private volatile boolean _exit = false;

    /**
     * Simple constructor that creates a fixed size window
     * @param renderer indicates which renderer to use LWJGL of JOGL
     * @param BulletScene indicates the base BulletScene that will be drawn
     */
    public ArdorWindow(int renderer, BulletScene scene) {

        /**
         *  Display settings width height and full screen  or not
         */
        final DisplaySettings settings = new DisplaySettings(800, 600, 24, 0,
                0, 8, 0, 0, false, false);

        /**
         * Create Renderer and our Window
         */
        switch (renderer) {
            case JOGL_RENDERER:
                final JoglCanvasRenderer joglRenderer = new JoglCanvasRenderer(scene);
                _canvas = new JoglCanvas(joglRenderer, settings);
                break;

            case LWJGL_RENDERER:
            default:
                final LwjglCanvasRenderer lwjglRenderer = new LwjglCanvasRenderer(scene);
                _canvas = new LwjglCanvas(lwjglRenderer, settings);
                break;
        }

        /**
         * Initilze out window
         */
        _canvas.init();

        /**
         * Set title to our window
         */
        _canvas.setTitle("Ardor3D");

        /**
         * Creating instance of timer
         */
        _timer = new Timer();

        /**
         * Store the BulletScene we will display
         */
        _scene = scene;
    }

    /**
     * Sets up basic camera, lighting and movement functionality
     */
    public void initialize() {
        
        // Move camera back so that we can see the origin
        _canvas.getCanvasRenderer().getCamera().setLocation(new Vector3(10, 10, 10));
        _canvas.getCanvasRenderer().getCamera().setDirection(new Vector3(-0.6933, -0.6933, -0.6933));
        _canvas.getCanvasRenderer().getCamera().setUp(new Vector3(-0.6933, 0.6933, -0.6933));
        _canvas.getCanvasRenderer().getCamera().setLeft(new Vector3(-0.707, 0, 0.707));
        
        // Setup physical and logical layers for mouse and keyboard
        PhysicalLayer physicalLayer = new PhysicalLayer(new LwjglKeyboardWrapper(), new LwjglMouseWrapper(), (LwjglCanvas)_canvas);
        _logicalLayer = new LogicalLayer();
        _logicalLayer.registerInput(_canvas, physicalLayer);

        // Setup logical triggers for FPS control
        FirstPersonControl control = new FirstPersonControl(_canvas.getCanvasRenderer().getCamera().getUp());
        control.setMouseRotateSpeed(0.002);
        control.setMoveSpeed(10.0);
        control.setupKeyboardTriggers(_logicalLayer);
        control.setupMouseTriggers(_logicalLayer, true, null);

    }

    /**
     * This is place where we update our BulletScene
     */
    public void update() {
        // see if we are closing windows
        if (_canvas.isClosing()) {
            _exit = true;
            return;
        }

        // Update timer so that time passed between frames can be calculated
        _timer.update();

        // Update controllers/render states/transforms/bounds
        _logicalLayer.checkTriggers(_timer.getTimePerFrame());
        _scene.update((float)_timer.getTimePerFrame());
    }

    /**
     * Main rendering/update loop
     */
    public void run() {
        // call init to build our BulletScene
        initialize();

        // Render and update our BulletScene.
        while (!_exit) {
            // update BulletScene
            update();

            // render our BulletScene
            _canvas.draw(null);

            // We are nice so we let other Thread play too (You must always be nice, or else)
            Thread.yield();
        }

        // destroy our window;
        _canvas.close();
    }

}
